﻿using System;

namespace ECommon
{
    /// <summary>
    /// try_catch_throw_finally封装工具
    /// </summary>
    public static class TryTool
    {
        /// <summary>
        /// 执行操作，遇到异常抛出
        /// </summary>
        /// <param name="then">要执行的操作</param>
        /// <returns>引用类型返回值</returns>
        public static void Try(Action then)
        {
            try
            {
                if (then != null)
                {
                    then();
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 执行操作，遇到异常执行操作后抛出
        /// </summary>
        /// <param name="then">要执行的操作</param>
        /// <param name="error">捕获异常的操作</param>
        /// <returns>引用类型返回值</returns>
        public static void Try(Action then, Action<Exception> error)
        {
            try
            {
                if (then != null)
                {
                    then();
                }
            }
            catch (Exception ex)
            {
                if (error != null)
                {
                    error(ex);
                }
                throw;
            }
        }

        /// <summary>
        /// 执行操作，遇到异常执行操作后抛出
        /// </summary>
        /// <param name="then">要执行的操作</param>
        /// <param name="error">捕获异常的操作</param>
        /// <param name="final">结束时的操作</param>
        /// <returns>引用类型返回值</returns>
        public static void Try(Action then, Action<Exception> error, Action final)
        {
            try
            {
                if (then != null)
                {
                    then();
                }
            }
            catch (Exception ex)
            {
                if (error != null)
                {
                    error(ex);
                }
                throw;
            }
            finally
            {
                if (final != null)
                {
                    final();
                }
            }
        }

        /// <summary>
        /// 执行带返回值的操作，遇到异常抛出
        /// </summary>
        /// <typeparam name="T">值类型的泛型</typeparam>
        /// <param name="then">要执行的操作，如果该操作为空，则抛出异常</param>
        /// <returns>值类型返回值</returns>
        /// <exception cref="ArgumentNullException">变量为空异常</exception>
        public static T Try<T>(Func<T> then)
        {
            try
            {
                if (then == null) { throw new ArgumentNullException("then", "要执行的带返回值的操作为空"); }
                return then();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 执行带返回值的操作，遇到异常执行操作后抛出
        /// </summary>
        /// <typeparam name="T">值类型的泛型</typeparam>
        /// <param name="then">要执行的操作，如果该操作为空，则抛出异常</param>
        /// <param name="error">捕获异常的操作</param>
        /// <returns>值类型返回值</returns>
        /// <exception cref="ArgumentNullException">变量为空异常</exception>
        public static T Try<T>(Func<T> then, Action<Exception> error)
        {
            try
            {
                if (then == null) { throw new ArgumentNullException("then", "要执行的带返回值的操作为空"); }
                return then();
            }
            catch (Exception ex)
            {
                if (error != null)
                {
                    error(ex);
                }
                throw;
            }
        }

        /// <summary>
        /// 执行带返回值的操作，遇到异常执行操作后抛出
        /// </summary>
        /// <typeparam name="T">值类型的泛型</typeparam>
        /// <param name="then">要执行的操作，如果该操作为空，则抛出异常</param>
        /// <param name="error">捕获异常的操作</param>
        /// <param name="final">结束时的操作</param>
        /// <returns>值类型返回值</returns>
        public static T Try<T>(Func<T> then, Action<Exception> error, Action final)
        {
            try
            {
                if (then == null) { throw new ArgumentNullException("then", "要执行的带返回值的操作为空"); }
                return then();
            }
            catch (Exception ex)
            {
                if (error != null)
                {
                    error(ex);
                }
                throw;
            }
            finally
            {
                if (final != null)
                {
                    final();
                }
            }
        }
    }
}